package com.common.model.exception;

import cn.hutool.core.util.StrUtil;
import com.common.utils.constant.Constants;
import com.common.model.result.Result;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * 描述：
 * 特殊异常处理
 * @author xianggj
 * @Date 2021/8/26 16:49
 **/
@ResponseBody
@RestControllerAdvice
public class SpecialExceptionHandler {

    private static final String BAD_REQUEST_MSG = "请求参数错误";

    @ExceptionHandler(value = { FileAnalysisException.class })
    public <T> Result<?> fileAnalysisException(FileAnalysisException e){
        e.printStackTrace();
        return Result.builder().code(HttpStatus.INTERNAL_SERVER_ERROR.value())
                .msg(e.getMessage()).build();
    }

    @ExceptionHandler(value = { FileNoSupportException.class })
    public <T> Result<?> fileNoSupportException(FileNoSupportException e){
        e.printStackTrace();
        return Result.builder().code(HttpStatus.INTERNAL_SERVER_ERROR.value())
                .msg(e.getMessage()).build();
    }

    @ExceptionHandler(value = { ParamNotNullException.class })
    public <T> Result<?> paramNotNullException(ParamNotNullException e){
        e.printStackTrace();
        return Result.builder().code(HttpStatus.INTERNAL_SERVER_ERROR.value())
                .msg(e.getMessage()).build();
    }

    @ExceptionHandler(value = { ParamFomatException.class })
    public <T> Result<?> paramFomatException(ParamFomatException e){
        e.printStackTrace();
        return Result.builder().code(HttpStatus.INTERNAL_SERVER_ERROR.value())
                .msg(e.getMessage()).build();
    }

    @ExceptionHandler(value = { ObjectNotFoundException.class })
    public <T> Result<?> objectNotFoundException(ObjectNotFoundException e){
        e.printStackTrace();
        return Result.builder().code(HttpStatus.NOT_FOUND.value())
                .msg(e.getMessage()).build();
    }

    @ExceptionHandler(value = { DataNotFoundException.class })
    public <T> Result<?> datanotFoundException(DataNotFoundException e){
        e.printStackTrace();
        return Result.builder().code(HttpStatus.NOT_FOUND.value())
                .msg(e.getMessage()).build();
    }

    @ExceptionHandler(value = { RemoteLinkException.class })
    public <T> Result<?> remoteLinkException(RemoteLinkException e){
        e.printStackTrace();
        return Result.builder().code(HttpStatus.INTERNAL_SERVER_ERROR.value())
                .msg(e.getMessage()).build();
    }

    @ExceptionHandler(value = { NotAuthorizationException.class })
    public <T> Result<?> notAuthorizationException(NotAuthorizationException e){
        e.printStackTrace();
        return Result.builder().code(4010)
                .msg(e.getMessage()).build();
    }



    @ExceptionHandler(value = { ServiceException.class })
    public <T> Result<?> serviceException(ServiceException e){
        e.printStackTrace();
        return Result.builder().code(HttpStatus.INTERNAL_SERVER_ERROR.value())
                .msg(e.getMessage()).build();
    }

    @ExceptionHandler(value = { NullPointerException.class })
    public <T> Result<?> nullPointerException(NullPointerException e){
        e.printStackTrace();
        return Result.builder().code(HttpStatus.INTERNAL_SERVER_ERROR.value())
                .msg("系统错误，请联系管理员").build();
    }

    @ExceptionHandler(value = { RuntimeBreakException.class })
    public <T> Result<?> runtimeBreakException(RuntimeBreakException e){
        e.printStackTrace();
        return Result.builder().code(HttpStatus.INTERNAL_SERVER_ERROR.value())
                .msg(e.getMessage()).build();
    }



    /**
     * 处理 form data方式调用接口校验失败抛出的异常
     * @return
     */
    @ExceptionHandler(BindException.class)
    public <T> Result<?>  bindExceptionHandler(BindException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        List<String> collect = fieldErrors.stream()
                .map(o -> o.getDefaultMessage())
                .collect(Collectors.toList());
       return Result.builder().code(HttpStatus.BAD_REQUEST.value())
               .msg(BAD_REQUEST_MSG + Constants.COLON + StrUtil.join(Constants.COMMA, collect))
               .build();
    }

    /**
     * 处理 json 请求体调用接口校验失败抛出的异常
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public <T> Result<?> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        List<String> collect = fieldErrors.stream()
                .map(o -> o.getDefaultMessage())
                .collect(Collectors.toList());
        return Result.builder().code(HttpStatus.BAD_REQUEST.value())
                .msg(BAD_REQUEST_MSG + Constants.COLON + StrUtil.join(Constants.COMMA, collect))
                .build();
    }

    /**
     *  处理单个参数校验失败抛出的异常
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public <T> Result<?> constraintViolationExceptionHandler(ConstraintViolationException e) {
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        List<String> collect = constraintViolations.stream()
                .map(o -> o.getMessage())
                .collect(Collectors.toList());
        return Result.builder().code(HttpStatus.BAD_REQUEST.value())
                .msg(BAD_REQUEST_MSG + Constants.COLON + StrUtil.join(Constants.COMMA, collect))
                .build();
    }

}
